home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Temp / UniqueInstance.m < prev   
Text File  |  1995-03-22  |  4KB  |  122 lines

  1. /******************************************************************************
  2.  
  3. .../UniqueInstance.m
  4.  
  5. Copyright Michael T. H. Scott, 1995.
  6.  
  7. UniqueInstance is a class which can have only one instance. Alloc, copy and free return error.
  8.  
  9. NOTE InterfaceBuilder uses _zoneAlloc() to create an instance of a custom object. It does not call +alloc. By overriding _zoneAlloc() for classes which respond to +uniqueInstance we guarantee that only one instance is ever allocated. It is necessary to remember that if multiple instances of a UniqueInstance subclass are included in an application's nib files then -init will be multiply called on that instance.
  10. ******************************************************************************/
  11.  
  12. #import "UniqueInstance.h"
  13. #import <objc/objc-runtime.h>
  14.  
  15. static id uniqueInstances = nil;
  16. static id initialized = nil;
  17. static const char *msg = "does not %s.\n";
  18. static id (*runtimeZoneAlloc)();
  19. static id uniqueInstanceZoneAlloc(Class aClass,
  20.                                   unsigned int indexedIvarBytes,
  21.                                   NXZone *zone);
  22.  
  23. @implementation UniqueInstance
  24.  
  25. /*-----------------------------------------------------------------------------
  26. Initializes the HashTable which will contain the unique instance for each UniqueInstance subclass.
  27. -----------------------------------------------------------------------------*/
  28. + initialize
  29. {
  30.     if ( self == [UniqueInstance class] )
  31.     {
  32.         uniqueInstances = [[HashTable allocFromZone: [self zone]]
  33.                                       initKeyDesc: "@"
  34.                                       valueDesc: "@"];
  35.                                       
  36.         initialized = [[List allocFromZone: [self zone]] init];
  37.                                       
  38.         runtimeZoneAlloc = _zoneAlloc;
  39.         _zoneAlloc = uniqueInstanceZoneAlloc;
  40.     }
  41.         
  42.     return self;
  43. }
  44.  
  45. /*-----------------------------------------------------------------------------
  46. Returns the unique instance of the receiving class.
  47. -----------------------------------------------------------------------------*/
  48. + uniqueInstance
  49. {
  50.     const void *key = (const void *)self;
  51.     id uniqueInstance = (id)[uniqueInstances valueForKey: key];
  52.     
  53.     if ( !uniqueInstance )
  54.     {
  55.         uniqueInstance = runtimeZoneAlloc(self, 0U, [self zone]);
  56.         [uniqueInstances insertKey: key value: (void *)uniqueInstance];
  57.         [uniqueInstance init];
  58.         [initialized addObject: uniqueInstance];
  59.     }
  60.     
  61.     return uniqueInstance;
  62. }
  63.  
  64. /*-----------------------------------------------------------------------------
  65. Reimplemented to return error.
  66. -----------------------------------------------------------------------------*/
  67. + alloc
  68. {
  69.     return [self error: msg, sel_getName(_cmd)];
  70. }
  71.  
  72. /*-----------------------------------------------------------------------------
  73. Returns whether the receiver is uninitialized.
  74. -----------------------------------------------------------------------------*/
  75. - (BOOL)uninitialized
  76. {
  77.     return [initialized indexOf: self] == NX_NOT_IN_LIST;
  78. }
  79.  
  80. /*-----------------------------------------------------------------------------
  81. Designated initializer.
  82. -----------------------------------------------------------------------------*/
  83. - init
  84. {
  85.     if ( [self uninitialized] ) [super init];
  86.     
  87.     return self;
  88. }
  89.  
  90. /*-----------------------------------------------------------------------------
  91. Reimplemented to return error.
  92. -----------------------------------------------------------------------------*/
  93. - copyFromZone: (NXZone *)aZone
  94. {
  95.     return [self error: msg, sel_getName(_cmd)];
  96. }
  97.  
  98. /*-----------------------------------------------------------------------------
  99. Reimplemented to return error.
  100. -----------------------------------------------------------------------------*/
  101. - free
  102. {
  103.     return [self error: msg, sel_getName(_cmd)];
  104. }
  105.  
  106. @end
  107.  
  108. /*-----------------------------------------------------------------------------
  109. Overrides _zoneAlloc to return the unique instance of a UniqueInstance subclasses.
  110. -----------------------------------------------------------------------------*/
  111. static id uniqueInstanceZoneAlloc(Class aClass,
  112.                                     unsigned int indexedIvarBytes,
  113.                                   NXZone *zone)
  114. {
  115.     if ( [aClass respondsTo: @selector(uniqueInstance)] )
  116.     {
  117.         return [aClass uniqueInstance];
  118.     }
  119.     
  120.     return runtimeZoneAlloc(aClass, indexedIvarBytes, zone);
  121. }
  122.